#pragma once

#include <iostream>
#include <unistd.h>
#include <sys/select.h>
#include "Sock.hpp"
#include "Pthread.hpp"

#define NUM 1024
#define FD_NONE -1
#define FD_USING -2

class Selete
{
public:
    Selete(std::string ip = "0.0.0.0", uint16_t port = 8080)
        : _ip(ip), _port(port), _maxfd(0)
    {
        Sock sock;
        _listensock = sock.Socket();
        sock.Bind(_listensock, _ip, _port);
        sock.Listen(_listensock);
        std::cout << "create sock cussess" << std::endl;

        for (int i = 0; i < NUM; i++)
        {
            _read_array[i] = FD_NONE;
        }
        _read_array[0] = _listensock;
    }

    ~Selete()
    {
        if (_listensock > 0)
        {
            close(_listensock);
        }
    }

    void Start()
    {
        fd_set rds;
        struct timeval tvl
        {
            0, 0
        };
        while (true)
        {
            FD_ZERO(&rds);
            for (int i = 0; i < NUM; i++)
            {
                if (_read_array[i] == FD_NONE)
                {
                    break;
                }
                FD_SET(_read_array[i], &rds);
                if (_read_array[i] > _maxfd)
                    _maxfd = _read_array[i];
            }
            Print();
            int ret = select(_maxfd + 1, &rds, nullptr, nullptr, nullptr);
            if (ret > 0)
            {
                // 读取成功
                std::cout << "read success" << std::endl;
                HandlerFunc(rds);
            }
            else if (ret == 0)
            {
                // 时间到了
                std::cout << "time out" << std::endl;
            }
            else
            {
                std::cout << "warning  errno: " << errno << "   strerror: " << strerror(errno) << std::endl;
            }
        }
    }

    void Print()
    {
        std::cout << "_read_array: ";
        for (int i = 0; i < NUM; i++)
        {
            if (_read_array[i] == FD_NONE)
            {
                return;
            }
            if (_read_array[i] != FD_USING)
                std::cout << _read_array[i] << " ";
        }
        std::cout << std::endl;
    }

    void Accept()
    {
        Sock sock;
        std::string ip;
        uint16_t port;
        int serversock = sock.Accept(_listensock, &ip, &port);
        std::cout << "创建新连接成功, 文件描述符: " << serversock << std::endl;
        // 将新连接加入数字当中
        int i = 0;
        for (i = 0; i < NUM; i++)
        {
            if (_read_array[i] == FD_NONE || _read_array[i] == FD_USING)
            {
                _read_array[i] = serversock;
                break;
            }
        }
        if (i == NUM)
        {
            // 文件描述符数组已经满了
            std::cout << "文件描述符已满，无法添加 " << std::endl;
        }
    }

    void Recv(int i)
    {
        Sock sock;
        std::string buffer;
        int n = sock.Revc(_read_array[i], buffer);
        if (n > 0)
        {
            // read success
            std::cout << "[" << _read_array[i] << "]  send message:  " << buffer;
        }
        else if (n == 0)
        {
            // 读端关闭
            std::cout << "you closed, me too" << std::endl;
            close(_read_array[i]);
            _read_array[i] = FD_USING;
        }
    }

    void HandlerFunc(fd_set &rds)
    {
        for (int i = 0; i < NUM; i++)
        {
            if (_read_array[i] == FD_NONE)
                break;
            if (_read_array[i] == FD_USING)
                continue;

            if (FD_ISSET(_read_array[i], &rds))
            {
                if (i == 0 && _read_array[i] == _listensock)
                {
                    // 获取新链接
                    Accept();
                }
                else
                {
                    // 读取数据，当前数据一定就绪
                    Recv(i);
                }
            }
        }
    }

private:
    int _listensock;
    int _read_array[NUM];
    int _maxfd;
    uint16_t _port;
    std::string _ip;
};